package dubbo.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


@Activate(group = {CommonConstants.CONSUMER,CommonConstants.PROVIDER})
public class DubboInvokeFilter implements Filter, Runnable {

    static Map<String, List<MethodInvokerInfo>> methodMap = new ConcurrentHashMap<>();

    public DubboInvokeFilter(){
        methodMap.put("methodA", new ArrayList<>());
        methodMap.put("methodB", new ArrayList<>());
        methodMap.put("methodC", new ArrayList<>());
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(this, 5, 5 , TimeUnit.SECONDS);
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime = System.currentTimeMillis();
        try {
            // 执行方法
            Result invoke = invoker.invoke(invocation);
            long endTime = System.currentTimeMillis();
            long time = endTime - startTime;

            String methodName = invocation.getMethodName();
            List<MethodInvokerInfo> methodInvokerInfoList = methodMap.get(methodName);

            // 每个方法第一次调用时，向map中存入这个方法的每一次调用信息
//            if(CollectionUtils.isEmpty(methodInvokerInfoList)){
//                methodMap.put(methodName, new ArrayList<>());
//            }
            // 缓存每一次的调用信息
            methodInvokerInfoList.add(new MethodInvokerInfo(startTime, endTime, time));

            return invoke;
        } finally {

        }
    }

    @Override
    public void run() {
        for(Map.Entry<String, List<MethodInvokerInfo>> item : methodMap.entrySet()){
            long currTime = System.currentTimeMillis();
            String methodName = item.getKey();
            Date date = new Date(currTime);
            System.out.println("===当前时间" + date + ": " + methodName + "方法的TP90:" + this.getTP(methodName, 0.9, currTime)
                    + ";方法的TP99:" + this.getTP(methodName, 0.99, currTime));
        }

        System.out.println("=======================================================================================");
    }

    public Long getTP(String method, double rate, Long currTime){
        Long time = 0L;

        Long startTime = currTime - 60*1000;

        List<MethodInvokerInfo> methodInvokerInfos = methodMap.get(method);
        List<Long> lastList = new ArrayList<>();
        for(MethodInvokerInfo item : methodInvokerInfos){
            if(item.getStart() >= startTime && item.getEnd() <= currTime ){
                lastList.add(item.getTime());
            }
        }

        if(lastList.size() > 0){
            Collections.sort(lastList);
            time = lastList.get((int) (lastList.size() * rate));
        }
        if(rate == 0.9){
            System.out.println(method + "===前1分钟被调用" + lastList.size());
        }
        return time;

//        List<MethodInvokerInfo> lastList = new ArrayList<>();
//        for(MethodInvokerInfo item : methodInvokerInfos){
//            if(item.getStart() <= startTime && item.getEnd() <= currTime ){
//                lastList.add(item);
//            }
//        }
//
//        Collections.sort(lastList, (o1, o2) -> {
//            if(o1.getTime() > o2.getTime()){
//                return 1;
//            }else {
//                return -1;
//            }
//        });
//
//        MethodInvokerInfo methodInvokerInfo = lastList.get((int) (lastList.size() * rate));
//        return methodInvokerInfo.getTime().toString();
    }
}
